﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using FNN.CustomFunctions;
using FNN.Helpers;
using FNN.NetworkMasters;
using FNN.Networks;
using FNN.SourcePoints;
using Microsoft.Win32;
using System.IO;

namespace GraphicFNN.Pages
{
    /// <summary>
    ///     Логика взаимодействия для CreationPage.xaml
    /// </summary>
    public partial class CreationPage : Page
    {
        public CreationPage()
        {
            InitializeComponent();
        }

        protected List<DateSourcePoint> GetFinancialDataSource(string pathToData)
        {
            var csvHelper = new FinancialCsvHelper(pathToData);
            var initialData = csvHelper.GetBody();
            var dataHeaders = csvHelper.GetHeader();
            var tempList = csvHelper.ProcessData(dataHeaders, initialData);
            List<DateSourcePoint> result = new List<DateSourcePoint>();

            foreach (var point in tempList)
            {
                result.Add((DateSourcePoint)point);
            }

            return result;
        }

        protected List<SourcePoint> GetDataSource(string pathToData)
        {
            CsvHelper csvHelper = null;

            switch ((NetworkMastersList)CmbType.SelectedIndex)
            {
                case NetworkMastersList.Financial:
                    csvHelper = new FinancialCsvHelper(pathToData);
                    break;
                case NetworkMastersList.Regular:
                    csvHelper = new RegularCsvHelper(pathToData);
                    break;
            }

            if (csvHelper == null) return null;

            var initialData = csvHelper.GetBody();
            var dataHeaders = csvHelper.GetHeader();
            var result = csvHelper.ProcessData(dataHeaders, initialData);

            return result;
        }

        private void ChbRandom_OnChecked(object sender, RoutedEventArgs e)
        {
            var grayBrush = Brushes.LightGray;
            TxtNetworkName.IsEnabled = false;
            TxtNetworkName.Background = grayBrush;
            TxtInputCount.IsEnabled = false;
            TxtInputCount.Background = grayBrush;
            TxtLayerCount.IsEnabled = false;
            TxtLayerCount.Background = grayBrush;
            TxtLayerNeuronCount.IsEnabled = false;
            TxtLayerNeuronCount.Background = grayBrush;
            TxtOutputCount.IsEnabled = false;
            TxtOutputCount.Background = grayBrush;
            CmbFunctions.IsEnabled = false;
        }

        private void ChbRandom_OnUnchecked(object sender, RoutedEventArgs e)
        {
            var whiteBrush = Brushes.White;
            TxtNetworkName.IsEnabled = true;
            TxtNetworkName.Background = whiteBrush;
            TxtInputCount.IsEnabled = true;
            TxtInputCount.Background = whiteBrush;
            TxtLayerCount.IsEnabled = true;
            TxtLayerCount.Background = whiteBrush;
            TxtLayerNeuronCount.IsEnabled = true;
            TxtLayerNeuronCount.Background = whiteBrush;
            TxtOutputCount.IsEnabled = true;
            TxtOutputCount.Background = whiteBrush;
            CmbFunctions.IsEnabled = true;
        }

        private void BtnCreate_OnClick(object sender, RoutedEventArgs e)
        {
            NetworkMaster netMaster = null;
            Network targetNetwork = null;
            var chartWindow = new ChartWindow();
            var currentDataSource = GetDataSource(TxtSourcePath.Text);

            switch ((NetworkMastersList)CmbType.SelectedIndex)
            {
                case NetworkMastersList.Financial:
                    netMaster = new FinancialNetworkMaster { PopulationCount = 3 };
                    ((FinancialNetworkMaster)netMaster).IterationResultsImproved += chartWindow.CatchResultsImproved;
                    ((FinancialNetworkMaster)netMaster).IterationChanged += chartWindow.CatchIterationChanged;
                    ((FinancialNetworkMaster)netMaster).DataSource = currentDataSource;
                    ((FinancialNetworkMaster)netMaster).ProfitPercent = 0;
                    targetNetwork = ChbRandom.IsChecked.HasValue && ChbRandom.IsChecked.Value
                        ? new FinancialNetwork()
                        : new FinancialNetwork(Convert.ToInt32(TxtInputCount.Text), Convert.ToInt32(TxtLayerCount.Text),
                            Convert.ToInt32(TxtLayerNeuronCount.Text),
                            new List<FunctionTypes> { (FunctionTypes)(CmbFunctions.SelectedIndex - 1) },
                            Convert.ToInt32(TxtOutputCount.Text));
                    break;
                case NetworkMastersList.Regular:
                    netMaster = new RegularNetworkMaster { PopulationCount = 3 };
                    ((RegularNetworkMaster)netMaster).IterationResultsImproved += chartWindow.CatchResultsImproved;
                    ((RegularNetworkMaster)netMaster).IterationResultsImproved += chartWindow.CatchResultsImproved;
                    ((RegularNetworkMaster)netMaster).DataSource = currentDataSource;
                    ((RegularNetworkMaster)netMaster).NeededErrorRate = -1;
                    targetNetwork = ChbRandom.IsChecked.HasValue && ChbRandom.IsChecked.Value
                        ? new RegularNetwork()
                        : new RegularNetwork(Convert.ToInt32(TxtInputCount.Text), Convert.ToInt32(TxtLayerCount.Text),
                            Convert.ToInt32(TxtLayerNeuronCount.Text),
                            new List<FunctionTypes> { (FunctionTypes)(CmbFunctions.SelectedIndex - 1) },
                            Convert.ToInt32(TxtOutputCount.Text));
                    break;
            }

            if (netMaster == null) return;
            targetNetwork.NetworkName = TxtNetworkName.Text;
            netMaster.IterationsLimit = 3000;
            netMaster.TimeLimit = 0;
            chartWindow.Show();

            var backgroundTask = Task.Factory.StartNew(() =>
            {
                var serializationHelper = new SerializationHelper();

                var resultNetwork = netMaster.TrainMultiNetwork(targetNetwork);
                var targetName = "";
                Dispatcher.Invoke(() =>
                {
                    chartWindow.Close();
                    targetName = TxtNetworkName.Text;
                    File.Copy(TxtSourcePath.Text, targetName + ".csv", true);
                    serializationHelper.WriteBinary(resultNetwork, targetName + ".fnn");
                });
            });
        }

        private void BtnSelectSource_OnClick(object sender, RoutedEventArgs e)
        {
            var fileBrowser = new OpenFileDialog
            {
                CheckFileExists = true,
                Multiselect = false,
                Filter = "CSV|*.csv"
            };
            fileBrowser.ShowDialog();
            TxtSourcePath.Text = fileBrowser.FileName;
        }
    }
}